package yunjiao.javatutorials.guava.concurrent;

import com.google.common.util.concurrent.Monitor;

import java.util.ArrayList;
import java.util.List;

/**
 * 线程安全缓冲池
 *
 * @author yangyunjiao
 */
public class ThreadSafeBuffer {
    private final Monitor monitor = new Monitor();
    private final List<Integer> buffer = new ArrayList<>();
    private final int capacity;

    private final Monitor.Guard notFull = new Monitor.Guard(monitor) {
        @Override
        public boolean isSatisfied() {
            return buffer.size() < capacity;
        }
    };

    private final Monitor.Guard notEmpty = new Monitor.Guard(monitor) {
        @Override
        public boolean isSatisfied() {
            return !buffer.isEmpty();
        }
    };

    public ThreadSafeBuffer(int capacity) {
        this.capacity = capacity;
    }

    public void produce(int item) throws InterruptedException {
        monitor.enterWhen(notFull);
        try {
            buffer.add(item);
            System.out.println("Produced: " + item + ", Buffer size: " + buffer.size());
        } finally {
            monitor.leave();
        }
    }

    public void consume() throws InterruptedException {
        monitor.enterWhen(notEmpty);
        try {
            Integer item = buffer.removeFirst();
            System.out.println("Consumed: " + item + ", Buffer size: " + buffer.size());
        } finally {
            monitor.leave();
        }
    }

    public boolean tryProduce(int item) {
        if (monitor.tryEnterIf(notFull)) {
            try {
                buffer.add(item);
                return true;
            } finally {
                monitor.leave();
            }
        }
        return false;
    }

    public int getSize() {
        monitor.enter();
        try {
            return buffer.size();
        } finally {
            monitor.leave();
        }
    }


}
